<?php

namespace App\Jobs\Finance\Traits;

use App\Models\Finance\FinanceCustomerBill;
use App\Models\Finance\FinanceShopSubAccountBill;
use App\Models\PriceRange;
use App\Models\QualityControlManage;
use App\Models\QuotaionInformation;
use App\Models\Shop;
use App\Models\SubAccount\SubAccountDataRecord;
use App\Models\WorkOverTime;

trait CreateBillTrait
{
    use CommonBillTrait;

    //客户子账号全部的开始结束时间
    public array $customerStartEnd=[];
    //某个店铺子账号全部的开始结束时间
    public array $shopStartEnd=[];

    //生成某个客户的账单
    public function singleCustomerBillCreate($customer){
        $this->customerStartEnd=[];
        if(count($customer->shopDetails)){
            //一个账单结算群一个总账单
            $groups=$this->groupShopDetails($customer->shopDetails);
            foreach ($groups as $wxGroup=>$shops){
                //客户总账单
                $billData=$this->customerBillData($customer,$wxGroup);
                $customerBill=$this->createCustomerBill($billData);
                $totalConsult=0;
                $totalDays=0;
                $groupPrice=[];
                //一个结算群的所有店铺
                foreach ($shops as $shopDetail){
                    if(count($shopDetail->subAccounts)){
                        $this->shopStartEnd=[];
                        $shopTotalConsult=0;
                        $shopSubIds=[];
                        foreach ($shopDetail->subAccounts as $subAccount){
                            if($subAccount->service_time_start<=$customerBill->bill_period_end){
                                //子账号账单详情
                                $subData=$this->subAccountBillData($customerBill,$shopDetail,$subAccount);
                                $subBill=$this->createSubAccountBill($subData);
                                $shopSubIds[]=$subBill->id;
                                $totalConsult+=$subData['consult_quantity'];
                                $shopTotalConsult+=$subData['consult_quantity'];
                                $totalDays+=$subData['service_days'];
                                $groupPrice[$subData['quotation_group_id']]['sub_bill_ids'][]=$subBill->id;
                                $groupPrice[$subData['quotation_group_id']]['sub_bill_consult'][]=$subData['consult_quantity'];
                                $groupPrice[$subData['quotation_group_id']]['group_start_end'][]=$this->getServicePeriod($subAccount,$customerBill->bill_period_start,$customerBill->bill_period_end);
                            }
                        }
//                        $rangePrice=$this->getShopQuotePrice($shopDetail,$shopTotalConsult);
                        $shopOtherFee=$this->getShopFee($shopDetail,$shopTotalConsult,$this->shopStartEnd);
                        $this->updateShopSubAccountPrice($shopSubIds,$shopOtherFee);
                    }
                }
                $this->updateFinalPrice($groupPrice);
                //更新总账单信息
                $this->updateTotalQuantity($customerBill,$totalConsult,$totalDays);
                $this->calcUpdateCustomerBillTotal($customerBill);

                //创建分部账单
                $this->createBranchBill($customerBill);
            }
        }
    }

    //店铺按结算群分组
    public function groupShopDetails($shopDetails){
        $group=[];
        foreach ($shopDetails as $shop){
            $settleGroup=$shop->quotaionInfo->wx_group;
            $group[$settleGroup][]=$shop;
        }
        return $group;
    }

    //本月是否生成过账单
    public function checkCustomerMonthBill($customer){
        return FinanceCustomerBill::where('bill_code',date('Ym').$customer->id)->count('id');
    }

    //客户账单数据
    public function customerBillData($customer,$wxGroup){
        $quotes=$this->getCustomerQuotes($customer);
        return [
            'customer_id'=>$customer->id,
            'company_name'=>$customer->company_name,
            'bill_type'=>$customer->advance_order,
            'bill_month'=>$this->getBillMonth($customer),
            'bill_date'=>$this->getBillDate($customer),
            'bill_code'=>date('Ym').$customer->id,
            'bill_period_start'=>$this->getBillPeriod($customer,'start'),
            'bill_period_end'=>$this->getBillPeriod($customer,'end'),
            'settlement_group'=>$wxGroup,
        ];
    }
    //获取客户报价信息
    public function getCustomerQuotes($customer){
        return Shop::where('customer_id',$customer->id)->get();
    }
    //账单属于哪个月
    public function getBillDate($customer){
        if($this->checkCustomerMonthBill($customer)){
            return date('Y-m');
        }
        return $this->getLastMonth();
    }
    //获取上个月
    public function getLastMonth(){
        $day = date('d');
        return date("Y-m", strtotime(-$day.' day'));
    }
    //获取账单结算群
    public function getGroups($quotes){
        $groups=$quotes->pluck('settlement_group')->toArray();
        $groups=array_unique($groups);
        return implode('，',$groups);
    }

    //客户账单创建
    public function createCustomerBill($billData){
        return FinanceCustomerBill::create($billData);
    }

    //核对子账号的服务时间
    public function checkServiceTime($subAccount,$customerBill){
        if(strtotime($subAccount->service_time_start)<=strtotime($customerBill->bill_period_end) && strtotime($subAccount->service_time_end)>=strtotime($customerBill->bill_period_start)){
            return true;
        }
        return false;
    }

    //子账号账单数据
    public function subAccountBillData($customerBill,$shopDetail,$subAccount){
        $consult=$this->getConsult($subAccount,$customerBill->bill_period_start,$customerBill->bill_period_end);
        $chargeStandard=$this->getChargeStandard($shopDetail,$consult,$customerBill);
        $overTimefee=$this->getOvertimeFee($subAccount,$customerBill->bill_period_start,$customerBill->bill_period_end);
        $serviceStartEnd=$this->getServicePeriod($subAccount,$customerBill->bill_period_start,$customerBill->bill_period_end);
        $this->customerStartEnd[]=$serviceStartEnd;
        $this->shopStartEnd[]=$serviceStartEnd;
        return [
            'bill_id'=>$customerBill->id,
            'customer_id'=>$customerBill->customer_id,
            'company_name'=>$customerBill->company_name,
            'shop_id'=>$shopDetail->id,
            'shop_name'=>$shopDetail->shop_name,
            'sub_account_id'=>$subAccount->id,
            'sub_account'=>$subAccount->sub_account,
            'service_period'=>$serviceStartEnd['start'].'-'.$serviceStartEnd['end'],
            'service_days'=>$serviceStartEnd['service_days'],
            'consult_column'=>$consult['column'],
            'consult_quantity'=>$consult['quantity'],
            'charge_standard'=>$chargeStandard['standard'],
//            'service_quote'=>$chargeStandard['price'],
            'wx_group'=>$chargeStandard['wx_group'],
            'quotation_change_status'=>$chargeStandard['quotation_change_status'],
            'quotation_group_id'=>$chargeStandard['quotation_group_id'],
            'overtime_fee'=>$overTimefee->sum('price'),
            'branch_overtime_fee'=>$overTimefee->sum('part_price'),
            'penalty_amount'=>$this->getPenalty('a_customer_couplet',$subAccount->id,$customerBill->bill_period_start,$customerBill->bill_period_end),
//            'shop_other_fee'=>$this->getShopFee($shopDetail,$consult),
        ];
    }
    //获取子账号登记的咨询量
    public function getConsult($subAccount,$billStart,$billEnd){
        $customColumn1='';
        $num=0;
        $records=SubAccountDataRecord::where('sub_account_id',$subAccount->id)
            ->where('created_at','>=',$billStart)
            ->where('created_at','<=',$billEnd.' 23:59:59')
            ->get();
        if(count($records)){
            foreach ($records as $record){
                if(!empty($record->custom_column1)){
                    $column1=json_decode($record->custom_column1,true);
                    $value=$column1['value']??0;
                    $num+=$value;
                    $customColumn1=$column1['label']??'';
                }
            }
        }
        if($customColumn1==''){
            $customColumn1=$subAccount->template->custom_column1??'';
        }
        return ['column'=>$customColumn1,'quantity'=>$num];
    }
    //获取客户报价（收费标准）
    public function getChargeStandard($shopDetail,$consult,$customerBill){
        $standard=null;
        $price=null;
        $lastStandard='';
        $lastPrice='';
        $wxGroup='';
        $changeStatus=0;
        $groupId=null;
        $quote=QuotaionInformation::find($shopDetail->quotaion_information_id);
        if($quote && $quote->priceRange && count($quote->priceRange)){
            foreach ($quote->priceRange as $range){
                if($standard==null){
                    $standard=$range->min.'~'.$range->max.':'.round($range->price);;
                }else{
                    $standard.=('</br>'.$range->min.'~'.$range->max.':'.round($range->price));
                }
                //匹配不上就用最后一行的
                $lastStandard=$range->min.'~'.$range->max.':'.$range->price;
                $lastPrice=$range->price;
            }
            if(strtotime($quote->updated_at)>strtotime($customerBill->bill_period_start) && strtotime($quote->updated_at)<strtotime($customerBill->bill_period_end)){
                $changeStatus=1;
            }
            $groupId=$quote->group_id;
            $wxGroup=$quote->wx_group;
        }
        return [
            'standard'=>$standard??$lastStandard,
            'price'=>$price??$lastPrice,
            'wx_group'=>$wxGroup,
            'quotation_change_status'=>$changeStatus,
            'quotation_group_id'=>$groupId,
        ];
    }
    //子账号账期总加班费
    public function getOvertimeFee($subAccount,$billStart,$billEnd){
        return WorkOverTime::where('sub_account_id',$subAccount->id)
            ->where('start','>=',$billStart)
            ->where('start','<=',$billEnd)
            ->get();
    }
    //子账号服务日期
    public function getServicePeriod($subAccount,$billStart,$billEnd){
        if(strtotime($subAccount->service_time_start)>strtotime($billStart) && strtotime($subAccount->service_time_start)<strtotime($billEnd)){
            $start=date('Y.m.d',strtotime($subAccount->service_time_start));
            $daysStart=$subAccount->service_time_start;
        }else{
            $start=date('Y.m.d',strtotime($billStart));
            $daysStart=$billStart;
        }
        if($subAccount->breakup_time && strtotime($subAccount->breakup_time)<strtotime($billEnd) && strtotime($subAccount->breakup_time)>strtotime($billStart)){
            $end=date('Y.m.d',strtotime($subAccount->breakup_time));
            $daysEnd=$subAccount->breakup_time;
        }else{
            $end=date('Y.m.d',strtotime($billEnd));
            $daysEnd=$billEnd;
        }
        return [
            'start'=>$start,
            'end'=>$end,
            'service_days'=>round((strtotime($daysEnd)-strtotime($daysStart))/24/3600)+1,
        ];
    }
    //获取店铺管理费
    public function getShopFee($shopDetail,$shopTotalConsult,$shopStartEnd){
        $shopDays=$this->getConsultDays($shopStartEnd);
        $dayConsult=$shopDays?round($shopTotalConsult/$shopDays,1):0;
        //跟日均咨询条件相比，不是总量
        if($shopDetail->need_fee==1 || $dayConsult<$shopDetail->consulation_volume){
            return 0;
        }
        return $shopDetail->manage_fee??0;
    }
    //获取罚款项
    public function getPenalty($column,$subAccountId,$start,$end){
        $likeId='%_'.$subAccountId.'_%';
        $where=[
            ['sub_account_id','like',$likeId],
            ['created_at','>=',$start],
            ['created_at','<=',$end],
        ];
        return QualityControlManage::where($where)->sum($column);
    }

    //创建子账号账单信息
    public function createSubAccountBill($subData){
        return FinanceShopSubAccountBill::create($subData);
    }

    //统计账期内各子账号总的量
    public function updateTotalQuantity($customerBill,$totalConsult,$totalDays){
        $consultDays=$this->getConsultDays($this->customerStartEnd);
        $customerBill->total_consult=$totalConsult;
        $customerBill->total_service_days=$totalDays;
        $customerBill->total_consult_days=$consultDays;
        $customerBill->day_average_consult=$consultDays?round($totalConsult/$consultDays,1):0;
        return $customerBill->save();
    }

    //获取最小时间和最大时间之间的天数
    public function getConsultDays($startEnd){
        if(!empty($startEnd)){
            $startEndArr=[];
            foreach ($startEnd as $item) {
                $startEndArr[]=strtotime(str_replace('.','-',$item['start']));
                $startEndArr[]=strtotime(str_replace('.','-',$item['end']));
            }
            sort($startEndArr);
            $diff=$startEndArr[count($startEndArr)-1]-$startEndArr[0];
            return round($diff/24/3600)+1;
        }
        return 0;
    }
    //匹配店铺报价的价格
    public function getShopQuotePrice($shopDetail,$shopTotalConsult){
        $final=null;
        $quote=QuotaionInformation::find($shopDetail->quotaion_information_id);
        if($quote && $quote->priceRange && count($quote->priceRange)){
            foreach ($quote->priceRange as $range){
                if($shopTotalConsult>$range->min && $shopTotalConsult<=$range->max){
                    return $range->price;
                }
                $final=$range->price;
            }
        }
        return $final;
    }
    //更新店铺账单详情相关数据
    public function updateShopSubAccountPrice($shopSubIds,$shopOtherFee){
        $data=[
//            'service_quote_final'=>$rangePrice,
            'shop_other_fee'=>$shopOtherFee,
        ];
        FinanceShopSubAccountBill::whereIn('id',$shopSubIds)->update($data);
    }
    //更新账单详情结算价格
    public function updateFinalPrice($groupPrice){
        foreach ($groupPrice as $groupId=>$group){
            $quoteTotal=array_sum($group['sub_bill_consult']);
            $totalDays=$this->getConsultDays($group['group_start_end']);
            $dayAverage=$totalDays?round($quoteTotal/$totalDays,1):0;
            $price=$this->getGroupqQuotePrice($groupId,$quoteTotal);
            $data=[
                'quote_total_consult'=>$quoteTotal,
                'total_quote_consult_days'=>$totalDays,
                'quote_day_average_consult'=>$dayAverage,
                'service_quote_final'=>$price,
            ];
            FinanceShopSubAccountBill::whereIn('id',$group['sub_bill_ids'])->update($data);
        }
    }
    //获取根据总量匹配到的区间价格，匹配不到用最高档
    public function getGroupqQuotePrice($groupId,$total){
        $final=null;
        $ranges=PriceRange::where('group_id',$groupId)->get();
        foreach ($ranges as $range){
            if($total>$range->min && $total<=$range->max){
                return $range->price;
            }
            $final=$range->price;
        }
        return $final;
    }


}
